﻿using Engine;
using System.Linq;
using TemplatesDatabase;
using System.Collections.Generic;
using System.Globalization;
using GameEntitySystem;
using Engine.Graphics;
using Engine.Media;
using Game;

namespace MMap
{
	public class SubsystemMMapFrameBlockBehaviour : SubsystemBlockBehavior, IDrawable
	{
        public SubsystemMMapBehaviour m_subsystemMMapBehaviour;
        public List<Point3> MapPoints = [];
        public int[] DrawOrders => SubsystemGlow.m_drawOrders;
        public PrimitivesRenderer3D m_primitivesRenderer3D = new();

		public override void Load(ValuesDictionary valuesDictionary)
		{
			base.Load(valuesDictionary);
            m_subsystemMMapBehaviour = Project.FindSubsystem<SubsystemMMapBehaviour>();
            ValuesDictionary keyValuePairs = valuesDictionary.GetValue<ValuesDictionary>("MapPoints", null);
            if (keyValuePairs != null)
            {
                IEnumerator<KeyValuePair<string, object>> enumerator = keyValuePairs.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    KeyValuePair<string, object> kvp = enumerator.Current;
                    if (kvp.Value is Point3 point && !MapPoints.Contains(point))
                        MapPoints.Add(point);
                }
            }
        }
        public override void Save(ValuesDictionary valuesDictionary)
		{
            ValuesDictionary valuesDictionary20 = [];
            valuesDictionary.SetValue("MapPoints", valuesDictionary20);
            int num = 0;
            foreach (var item in MapPoints)
            {
                valuesDictionary20.SetValue(num.ToString(), item);
                num++;
            }
        }
        public override void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ)
        {
            int cellValue = SubsystemTerrain.Terrain.GetCellValue(x, y, z), cellId = Terrain.ExtractContents(cellValue), cellData = Terrain.ExtractData(cellValue);
            if (cellId == BlocksManager.GetBlockIndex<MMapFrameBlock>())
            {
                Point3 point = new Point3(x, y, z) + CellFace.FaceToPoint3(MMapFrameBlock.GetRotation(cellData));
                int cellContents = SubsystemTerrain.Terrain.GetCellContents(point.X, point.Y, point.Z);
                if (BlocksManager.Blocks[cellContents].IsTransparent || !BlocksManager.Blocks[cellContents].IsCollidable)
                    SubsystemTerrain.DestroyCell(0, x, y, z, 0, noDrop: false, noParticleSystem: false);
            }
        }

		public override void OnBlockModified(int value, int oldValue, int x, int y, int z)
		{//data值改变时
            int id = Terrain.ExtractContents(value), data = Terrain.ExtractData(value);
            if(id == BlocksManager.GetBlockIndex<MMapFrameBlock>() && Terrain.ExtractContents(oldValue) == BlocksManager.GetBlockIndex<MMapFrameBlock>())
			{
                Point3 point = new(x, y, z);
                if(data > 0 && !MapPoints.Contains(point))
                    MapPoints.Add(point);
                if (data <= 0 && MapPoints.Contains(point))
				{
                    MapPoints.Remove(point);
                }
            }
        }

		public override void OnBlockRemoved(int value, int newValue, int x, int y, int z)
		{
            Point3 point = new(x, y, z);
			MapPoints.Remove(point);
		}

        public void Draw(Camera camera, int drawOrder)
		{
            for(int i = MapPoints.Count - 1; i >= 0; i--)
			{
                Point3 point = MapPoints[i];
                int cellValue = SubsystemTerrain.Terrain.GetCellValue(point.X, point.Y, point.Z), cellData = Terrain.ExtractData(cellValue);
                Vector3 center = new Vector3(point) + new Vector3(0.5f);
                if(Vector3.Distance(camera.ViewPosition, center) < SettingsManager.VisibilityRange)
                {
                    int rotation = MMapFrameBlock.GetRotation(cellData), mapData = MMapFrameBlock.GetMapData(cellData);
                    if(m_subsystemMMapBehaviour.MapContents.TryGetValue(mapData, out MMapContent mapContent))
					{
                        float w = 0.05f;//展示框的厚度
                        Vector3 p0, p1;
                        switch(rotation)
                        {
                            case 1:
                                p0 = new Vector3(0.5f - w, 0.5f, -0.5f);
                                p1 = new Vector3(0.5f - w, 0.5f, 0.5f);
                                break;
                            case 2:
                                p0 = new Vector3(-0.5f, 0.5f, w - 0.5f);
                                p1 = new Vector3(0.5f, 0.5f, w - 0.5f);
                                break;
                            case 3:
                                p0 = new Vector3(w - 0.5f, 0.5f, 0.5f);
                                p1 = new Vector3(w - 0.5f, 0.5f, -0.5f);
                                break;
                            default:
                                p0 = new Vector3(0.5f, 0.5f, 0.5f - w);
                                p1 = new Vector3(-0.5f, 0.5f, 0.5f - w);
                                break;
                        }
                        Vector3 p2 = p1 - Vector3.UnitY, p3 = p0 - Vector3.UnitY;

                        float num4 = LightingManager.LightIntensityByLightValue[SubsystemTerrain.Terrain.GetCellLight(point.X, point.Y, point.Z)];
                        Color color = new(num4, num4, num4);

                        TexturedBatch3D texturedBatch = m_primitivesRenderer3D.TexturedBatch(mapContent.RenderTarget2D, useAlphaTest: false, 0, null, RasterizerState.CullNoneScissor, BlendState.AlphaBlend, SamplerState.PointWrap);
                        texturedBatch.QueueQuad(center + p0, center + p1, center + p2, center + p3, Vector2.Zero, Vector2.UnitX, Vector2.One, Vector2.UnitY, color);
					}
                }

            }
            m_primitivesRenderer3D.Flush(camera.ViewProjectionMatrix);
		}


    }
}
